home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / drv_mac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-30  |  24.2 KB  |  985 lines  |  [TEXT/MMCC]

  1. /*==============================================================================
  2. Project:    SPD
  3.  
  4. File:    drv_mac.c
  5.  
  6. Description:
  7. Mac-specific code for initialization & displaying command-line options & output window.
  8. ------------------------------------------------------------------------------
  9. Author:
  10.     Alexander Enzmann, [70323,2461]
  11.     Eduard Schwan, [71513,2161]
  12. ------------------------------------------------------------------------------
  13. Change History:
  14.     9212??    [ae]    Created.
  15.     921214    [esp]    Updated to compile under MPW C as well as Think C.
  16.     930117    [esp]    Added MacInit, MacMultiTask, MacShutDown, GetOptions code
  17.     930317    [esp]    Added MoveToMaxDevice, environs check, collapsed multiple
  18.                     dialogs to 1, changed display_init to accept bg_color
  19.     930418    [esp]    Added driver checks.
  20.     930803    [esp]    Changed argv parameters to match new 3.1a format.
  21.     930805    [esp]    Added radios for the -t/-c output_format switches.
  22.     930817    [esp]    Added ColorQD check in Display_Init.
  23.     930918    [esp]    Fixed up logic for input parm prompting.
  24.     930918    [esp]    Added grody quick fix to redraw please-wait dlg on switchin.
  25.     940725    [esp]    Removed special palette, use System palette to avoid Finder color snatching
  26.     950422    [esp]    Changed popup menu handling to simpler System 7-only control style
  27. ==============================================================================*/
  28.  
  29. #include <stdio.h>        /* sprintf, etc */
  30. #include <stdlib.h>        /* atoi, etc */
  31.  
  32. /*==== Macintosh-specific headers ====*/
  33. #include <Controls.h>
  34. #include <Desk.h>
  35. #include <Dialogs.h>
  36. #include <Files.h>
  37. #include <Memory.h>            /* BlockMove */
  38. #include <Menus.h>
  39. #include <OSEvents.h>
  40. #include <OSUtils.h>
  41. #include <Packages.h>
  42. #include <QuickDraw.h>
  43. #include <Palettes.h>
  44. #include <Resources.h>
  45. #include <Types.h>
  46. #include <Windows.h>
  47. #include <sound.h>
  48. #include <AppleEvents.h>
  49. #include <GestaltEqu.h>
  50. #include <Folders.h>
  51. #include <errors.h>            /* dupFNErr, etc */
  52. #include <Fonts.h>            /* checkMark */
  53. #include <segload.h>        /* UnloadSeg */
  54. #include <traps.h>            /* _Unimplemented */
  55. #include <StandardFile.h>    /* SFPutFile */
  56. #include <string.h>            /* strcpy/cat */
  57. #include <toolutils.h>        /* BitTst, GetCursor, etc */
  58.  
  59. #ifdef applec
  60. #include <strings.h>        /* p2cstr */
  61. #endif
  62.  
  63. #include "def.h"
  64. #include "drv.h"
  65. #include "lib.h"        /* for output types */
  66.  
  67.  
  68. /*------------------------------------------------------------*/
  69. #define    kOSEvent                app4Evt    /* event used by MultiFinder */
  70. #define    kSuspendResumeMessage    1        /* high byte of suspend/resume event message */
  71.  
  72. #define kMouseCursorID 1000    // mouse cursor resource ID
  73.  
  74. /* turn on to attach special palette */
  75. /* #define    USE_CUSTOM_PALETTE        1
  76.  
  77.  
  78. /*------------------------------------------------------------*/
  79. // constants for positioning the default popup item within its box
  80. #define    SLOP_LEFT    13        // leave this much space on left of title
  81. #define    SLOP_RIGHT    12        // this much on right
  82. #define    SLOP_BOTTOM     5        // this much below baseline
  83.  
  84. // general dialog constants
  85. #define    DlogID_BADENV        1000
  86. #define    DlogID_WAIT            1001
  87. #define    DlogID_NOCOLORQD    1002
  88. #define    DlogID_GETOPTS        2000
  89.  
  90. // # of lines or pixels to draw between multitask calls
  91. #define    MAX_TASK_WAIT    20
  92.  
  93.  
  94. /*------------------------------------------------------------*/
  95. short        gMacRayTracerKind = OUTPUT_RT_DEFAULT;
  96. short        gMacParmSize = 2;
  97. Boolean        gMacDoBuiltIn = true;    /* TRUE= OUTPUT_CURVES, FALSE = OUTPUT_PATCHES */
  98. char        gInFileName[64];
  99.  
  100.  
  101. /*------------------------------------------------------------*/
  102. static WindowPtr    myWindow;
  103.  
  104. #if defined(USE_CUSTOM_PALETTE)
  105. static PaletteHandle PolyPalette;
  106. #endif
  107.  
  108. static int            maxx = 460;
  109. static int            maxy = 300;
  110. static int            gMultiTaskCount = 0;
  111.  
  112. static Boolean        gHasSizePrompt;
  113. static Boolean        gHasInFilePrompt;
  114. static Boolean        gHasPatchPrompt;
  115.  
  116. static COORD3        bkgnd_color;
  117. static int            display_active_flag = 0;
  118. static double        X_Display_Scale = 1.0;
  119. static double        Y_Display_Scale = 1.0;
  120. static SysEnvRec    gSysEnvirons;
  121. static DialogPtr    gDialogPtr = NULL;
  122.  
  123. static char            *macArgv[] =    {NULL, NULL, NULL, NULL, NULL,
  124.                                     NULL, NULL, NULL, NULL, NULL};
  125. static char            macArgvBuffer[200];        // fake argc/argv
  126. static char            *argvCurrent;
  127.  
  128.  
  129. /*------------------------------------------------------------*/
  130. void MacMultiTask();
  131.  
  132.  
  133. /*------------------------------------------------------------*/
  134. #pragma segment main
  135.  
  136.  
  137. /*------------------------------------------------------------*/
  138. /* Returns the short version string in the application's version resource */
  139. static void GetAppVersionPString(short versID, Str31 versionString)
  140. {
  141.     VersRecHndl    versHandle;        // VersRecHndl declared in MPW's <files.h>
  142.  
  143.     /* Get the resource string from app, 'vers' versID (1 or 2) resource! */
  144.     versionString[0] = '\0';
  145.     versHandle = (VersRecHndl)GetResource('vers',versID);
  146.     if (versHandle)
  147.     {
  148.         HLock((Handle)versHandle);
  149.         BlockMove((**versHandle).shortVersion, versionString,
  150.                     (**versHandle).shortVersion[0]+1);
  151.         ReleaseResource((Handle)versHandle);
  152.     }
  153. } // GetAppVersionPString
  154.  
  155.  
  156. /*------------------------------------------------------------*/
  157. static void MoveWindowToMaxDevice(WindowPtr theWindow)
  158. {
  159.     Point        upperCorner;
  160.     Rect        mainRect;
  161.     Rect        deviceRect;
  162.     Rect        windRect;
  163.     Rect        maxDragBounds;
  164.     GDHandle    theMainGDevice, theMaxGDevice;
  165.  
  166.     if (theWindow == NULL)
  167.         return;
  168.  
  169.     // Set up bounds for all devices
  170.     SetRect(&maxDragBounds, -16000, -16000, 16000, 16000);
  171.  
  172.     // Find main screen bounds
  173.     theMainGDevice = GetMainDevice();
  174.     mainRect = (**theMainGDevice).gdRect;
  175.  
  176.     // Find deepest screen bounds
  177.     theMaxGDevice = GetMaxDevice(&maxDragBounds);
  178.     deviceRect = (**theMaxGDevice).gdRect;
  179.  
  180.     // if Max is the same as Main, we need do nothing! Already in place!
  181.     if (EqualRect(&mainRect, &deviceRect))
  182.         return;
  183.  
  184.     // where's the window, relative to main screen
  185.     windRect = theWindow->portRect;
  186.     // yah, but where is it really?
  187.     SetPort(theWindow);
  188.     LocalToGlobal((Point*)&windRect.top);
  189.     LocalToGlobal((Point*)&windRect.bottom);
  190.  
  191.     // find relative spot on new device
  192.     upperCorner.h = windRect.left;
  193.     upperCorner.v = windRect.top;
  194.     // now relative to new screen
  195.     upperCorner.h = upperCorner.h + deviceRect.left;
  196.     upperCorner.v = upperCorner.v + deviceRect.top;
  197.  
  198.     // now move it there
  199.     MoveWindow(theWindow, upperCorner.h, upperCorner.v, true);
  200.  
  201. } // MoveWindowToMaxDevice
  202.  
  203.  
  204.  
  205. /*------------------------------------------------------------*/
  206. // This is a user item proc for drawing default dialog button outlines */
  207. static pascal void outlineDefaultButton(DialogPtr theDialog, short theItem)
  208. {
  209. #pragma unused (theItem)
  210.     PenState    SavePen;
  211.     short        itemType;
  212.     Handle        itemHandle;
  213.     Rect        dispRect;
  214.  
  215.     GetPenState(&SavePen);
  216.     /* use 'ok' (#1) item's rectangle */
  217.     GetDItem(theDialog, ok, &itemType, &itemHandle, &dispRect);
  218.     SetPort(theDialog);
  219.     PenSize(3, 3);
  220.     InsetRect(&dispRect, -4, -4);
  221.     FrameRoundRect(&dispRect, 16, 16);
  222.     SetPenState(&SavePen);
  223. } // outlineDefaultButton
  224.  
  225.  
  226. /*------------------------------------------------------------*/
  227. /* Sets dialog #3 item's display proc to draw outline around item #1 */
  228. static void SetupDefaultButton(DialogPtr theDialog)
  229. {
  230.     short    itemtype;
  231.     Rect    itemrect;
  232.     Handle    tempHandle;
  233.  
  234.     /* Set up User item (always #3) to display a border around OK button (#1) */
  235.     GetDItem(theDialog, 3, &itemtype, &tempHandle, &itemrect);
  236.     SetDItem(theDialog, 3, itemtype, (Handle)&outlineDefaultButton, &itemrect);
  237. } // SetupDefaultButton
  238.  
  239.  
  240. /*------------------------------------------------------------*/
  241. // Move a dialog item (whatever type it is) to absolute position h,v
  242. static void MoveDItem(DialogPtr theDialog, short theItemID, short h, short v)
  243. {
  244.     short    itemtype;
  245.     Rect    itemrect;
  246.     Handle    tempHandle;
  247.  
  248.     // NOTE: We should check for CtrlItem here and call MoveControl instead, just lazy!
  249.     // get item
  250.     GetDItem(theDialog, theItemID, &itemtype, &tempHandle, &itemrect);
  251.     // move its view rect (to absolute pos)
  252.     OffsetRect(&itemrect, h-itemrect.left, v-itemrect.top);
  253.     // set new rect value back into item
  254.     SetDItem(theDialog, theItemID, itemtype, tempHandle, &itemrect);
  255. } // MoveDItem
  256.  
  257.  
  258. /*------------------------------------------------------------*/
  259. static DialogPtr SetupNewDialog(short theDialogID, Boolean doOutlineDefault)
  260. {
  261.     DialogPtr    aDialog;
  262.  
  263.     aDialog = GetNewDialog(theDialogID, NULL, (WindowPtr)-1);
  264.  
  265.     /* "default" the OK button */
  266.     if ((aDialog != NULL) && doOutlineDefault)
  267.         SetupDefaultButton(aDialog);
  268.  
  269.     return aDialog;
  270.  
  271. } // SetupNewDialog
  272.  
  273.  
  274. /*------------------------------------------------------------*/
  275. static void FatalErrDialog(short DlogID)
  276. {
  277.     short        itemHit;
  278.  
  279.     SysBeep(4);
  280.     gDialogPtr = SetupNewDialog(DlogID, true);
  281.     if (gDialogPtr)
  282.     {
  283.         ShowWindow(gDialogPtr);
  284.         ModalDialog(NULL, &itemHit);
  285.     }
  286.     else
  287.     {
  288.         /* two beeps means something is very wrong! */
  289.         SysBeep(4);
  290.     }
  291.     ExitToShell();
  292. } // FatalErrDialog
  293.  
  294.  
  295. /*------------------------------------------------------------*/
  296. static Boolean GetInputFile(char * theInFileName)
  297. {
  298.     SFReply        reply;
  299.     Point        where;
  300.     SFTypeList    theTypes;
  301.  
  302.     where.h = 30;
  303.     where.v = 50;
  304.  
  305.     /* prompt */
  306.     theTypes[0] = 'TEXT';
  307.     SFGetFile(where, "\p", (FileFilterProcPtr)NULL, 1, theTypes, (DlgHookProcPtr)NULL, &reply);
  308.     if (reply.good)
  309.     {
  310.         /* return it */
  311.         BlockMove(reply.fName, theInFileName, 1+reply.fName[0]);
  312.         p2cstr((StringPtr)theInFileName);
  313.         SetVol(NULL, reply.vRefNum); /* set current folder */
  314.         return true;
  315.     }
  316.     else
  317.         return false;
  318. } // GetInputFile
  319.  
  320.  
  321. /*------------------------------------------------------------*/
  322. #ifdef FUTURE_USE
  323. static Boolean GetOutputFile(char * theOutFileName)
  324. {
  325.     SFReply        reply;
  326.     Point        where;
  327.     char        pOutFileName[64];
  328.  
  329.     GetBestDlgPoint(&where);
  330.     /* pre-fill output filename with old one */
  331.     strcpy(pOutFileName, theOutFileName);
  332.     c2pstr(pOutFileName);
  333.     /* prompt */
  334.     SFPutFile(where, "\pCreate output file.", pOutFileName,
  335.                 (DlgHookProcPtr)NULL, &reply);
  336.     if (reply.good)
  337.     {
  338.         /* return it */
  339.         BlockMove(reply.fName, theOutFileName, 1+reply.fName[0]);
  340.         p2cstr(theOutFileName);
  341.         SetVol(NULL, reply.vRefNum); /* set current folder */
  342.         return true;
  343.     }
  344.     else
  345.         return false;
  346. } // GetOutputFile
  347.  
  348. #endif FUTURE_USE
  349.  
  350.  
  351. /*------------------------------------------------------------*/
  352. static void
  353. ToolBoxInit()
  354. {
  355.     int            k;
  356.     EventRecord    anEvent;
  357.  
  358.     InitGraf(&qd.thePort);
  359.     InitFonts();
  360.     InitWindows();
  361.     InitMenus();
  362.     TEInit();
  363.     InitDialogs(0L);
  364.     InitCursor();
  365.  
  366.     /* create master pointer blocks for heap o' mallocs */
  367.     for (k=0; k<8; k++)
  368.         MoreMasters();
  369.  
  370.     // DTS Hocus Pocus to bring our app to the front
  371.     for (k = 1; k <= 3; k++)
  372.         EventAvail(everyEvent, &anEvent);
  373.  
  374.     // what kind of environment are we in, anyway?
  375.     SysEnvirons(1, &gSysEnvirons);
  376.     if    (
  377.         (gSysEnvirons.machineType < envMachUnknown)
  378.     ||    (gSysEnvirons.systemVersion < 0x0700)
  379.     ||    (gSysEnvirons.processor < env68020)
  380.         )
  381.     {
  382.         FatalErrDialog(DlogID_BADENV);
  383.     }
  384. }
  385.  
  386.  
  387. /*------------------------------------------------------------*/
  388. #if defined(USE_CUSTOM_PALETTE)
  389. static int
  390. determine_color_index(color)
  391.    COORD3 color;
  392. {
  393.    int i;
  394.    unsigned char r, g, b;
  395.  
  396.    i = 255.0 * color[Z];
  397.    if (i<0) i=0;
  398.    else if (i>=256) i = 255;
  399.    b = (unsigned char)i;
  400.  
  401.    i = 255.0 * color[Y];
  402.    if (i<0) i=0;
  403.    else if (i>=256) i = 255;
  404.    g = (unsigned char)i;
  405.  
  406.    i = 255.0 * color[X];
  407.    if (i<0) i=0;
  408.    else if (i>=256) i = 255;
  409.    r = (unsigned char)i;
  410.  
  411.    return (r & 0xE0) | ((g & 0xE0) >> 3) | (b >> 6);
  412. } // determine_color_index
  413. #endif
  414.  
  415.  
  416. /*------------------------------------------------------------*/
  417. void Coord3ToRGBColor(COORD3 c3color, RGBColor    * rgbc)
  418. {
  419.    rgbc->red    = c3color[R_COLOR]*65535.0;
  420.    rgbc->green  = c3color[G_COLOR]*65535.0;
  421.    rgbc->blue   = c3color[B_COLOR]*65535.0;
  422. } // Coord3ToRGBColor
  423.  
  424.  
  425. /*------------------------------------------------------------*/
  426. void display_clear()
  427. {
  428.    Rect re;
  429.  
  430. #if defined(USE_CUSTOM_PALETTE)
  431.    PmForeColor(determine_color_index(bkgnd_color));
  432. #else
  433.    RGBColor    rgbc;
  434.  
  435.    Coord3ToRGBColor(bkgnd_color, &rgbc);
  436.    RGBForeColor(&rgbc);
  437. #endif
  438.    re.top = 0;
  439.    re.left = 0;
  440.    re.right = maxx;
  441.    re.bottom = maxy;
  442.    PaintRect(&re);
  443. }
  444.  
  445.  
  446. /*------------------------------------------------------------*/
  447. void
  448. display_init(xres, yres, bk_color)
  449.    int xres, yres;
  450.    COORD3 bk_color;
  451. {
  452.    RGBColor c;
  453.    int i;
  454.    int r, g, b;
  455.    Rect re;
  456.    COORD3 cColor;
  457.  
  458.     // die if on a machine that has no Color QD
  459.    if (!gSysEnvirons.hasColorQD)
  460.    {
  461.         FatalErrDialog(DlogID_NOCOLORQD);
  462.    }
  463.  
  464.    // remember the background color
  465.    COPY_COORD3(bkgnd_color, bk_color);
  466.  
  467.    // if already displaying, just clear the screen and return
  468.    if (display_active_flag) {
  469.       display_clear();
  470.       return;
  471.       }
  472.  
  473.    display_active_flag = 1;
  474.  
  475.    re.top = 24;
  476.    re.left = 4;
  477.    re.right = re.left + maxx;
  478.    re.bottom = re.top + maxy;
  479.    myWindow = NewCWindow(0L, &re, "\pObject Display",
  480.             FALSE, plainDBox,
  481.             (WindowPtr)-1L, FALSE, 0L);
  482.  
  483. #if defined(USE_CUSTOM_PALETTE)
  484.    PolyPalette = NewPalette(256, 0L, pmTolerant, 0x0000);
  485.    c.red = c.green = c.blue = 0;
  486.    SetEntryColor(PolyPalette, 0, &c);
  487.  
  488.    i = 0;
  489.    for (r=0;r<8;r++)
  490.       for (g=0;g<8;g++)
  491.      for (b=0;b<4;b++) {
  492.         c.red   = r << 13;
  493.         c.green = g << 13;
  494.         c.blue  = b << 14;
  495.         SetEntryColor(PolyPalette, i, &c);
  496.         i++;
  497.         }
  498.  
  499.    /* Make sure the last entry is true white */
  500.    c.red   = 0xFFFF;
  501.    c.green = 0xFFFF;
  502.    c.blue  = 0xFFFF;
  503.    SetEntryColor(PolyPalette, i-1, &c);
  504.    SetEntryColor(PolyPalette, 0xFF, &c);
  505.  
  506.    SetPalette(myWindow, PolyPalette, TRUE);
  507. #endif
  508.  
  509.    /* Now open the window. */
  510.    MoveWindowToMaxDevice(myWindow);
  511.    ShowWindow(myWindow);
  512.    SetPort(myWindow);
  513.  
  514.    display_clear();
  515.  
  516.    if (xres > maxx)
  517.       X_Display_Scale = (double)maxx / (double)xres;
  518.    else
  519.       X_Display_Scale = 1.0;
  520.    if (yres > maxy)
  521.       Y_Display_Scale = (double)maxy / (double)yres;
  522.    else
  523.       Y_Display_Scale = 1.0;
  524.  
  525.    if (X_Display_Scale < Y_Display_Scale)
  526.       Y_Display_Scale = X_Display_Scale;
  527.    else if (Y_Display_Scale < X_Display_Scale)
  528.       X_Display_Scale = Y_Display_Scale;
  529.  
  530.    /* Outline the actual "visible" display area in the window */
  531.    SET_COORD3(cColor, 0.5, 0.5, 0.5); // grey
  532.    if (X_Display_Scale == 1.0) {
  533.       display_line(-xres/2, -yres/2, -xres/2, yres/2, cColor);
  534.       display_line( xres/2, -yres/2,  xres/2, yres/2, cColor);
  535.       }
  536.    if (Y_Display_Scale == 1.0) {
  537.       display_line(-xres/2,  yres/2,  xres/2,  yres/2, cColor);
  538.       display_line(-xres/2, -yres/2,  xres/2, -yres/2, cColor);
  539.       }
  540.  
  541.    return;
  542. }
  543.  
  544. /*------------------------------------------------------------*/
  545. void
  546. display_close(wait_flag)
  547.    int wait_flag;
  548. {
  549.     EventRecord    anEvent;
  550.     CursHandle    mouseCursorH;
  551.  
  552.     InitCursor(); // set it back to arrow
  553.     if (gDialogPtr)
  554.         DisposeDialog(gDialogPtr);
  555.  
  556.     mouseCursorH = GetCursor(kMouseCursorID);
  557.     if (mouseCursorH)
  558.         SetCursor(*mouseCursorH);
  559.  
  560.     /* hang around until the user is finished (this is grody, but works) */
  561.     if (wait_flag)
  562.     {
  563.         SysBeep(4);
  564.         while (!Button())
  565.             EventAvail(everyEvent, &anEvent);
  566.     }
  567.  
  568.     /* when all done, close the window on exit */
  569.     if (myWindow)
  570.         CloseWindow(myWindow);
  571.  
  572.     InitCursor(); // set it back to arrow
  573. }
  574.  
  575. /*------------------------------------------------------------*/
  576. static void
  577. putpixel(x, y, color)
  578.    int x, y;
  579.    COORD3 color;
  580. {
  581.    Rect r;
  582. #if defined(USE_CUSTOM_PALETTE)
  583.    int color_index;
  584. #else
  585.    RGBColor    rgbc;
  586. #endif
  587.  
  588.    r.top = y;
  589.    r.left = x;
  590.    r.bottom = y+1;
  591.    r.right = x+1;
  592. #if defined(USE_CUSTOM_PALETTE)
  593.    color_index = determine_color_index(color);
  594.    PmForeColor(color_index);
  595. #else
  596.    Coord3ToRGBColor(color, &rgbc);
  597.    RGBForeColor(&rgbc);
  598. #endif
  599.    PaintRect(&r);
  600.    return;
  601. }
  602.  
  603. /*------------------------------------------------------------*/
  604. void
  605. display_plot(x, y, color)
  606.    int x, y;
  607.    COORD3 color;
  608. {
  609.    double xt, yt;
  610.  
  611.    MacMultiTask();
  612.    yt = maxy/2 - Y_Display_Scale * y;
  613.    xt = maxx/2 + X_Display_Scale * x;
  614.  
  615.    if (xt < 0.0) x = 0;
  616.    else if (xt > 320.0) x = 320;
  617.    else x = (int)xt;
  618.    if (yt < 0.0) y = 0;
  619.    else if (yt > 240.0) y = 240;
  620.    else y = (int)yt;
  621.  
  622.    putpixel(x, y, color);
  623. }
  624.  
  625. /*------------------------------------------------------------*/
  626. void
  627. display_line(x0, y0, x1, y1, color)
  628.    int x0, y0, x1, y1;
  629.    COORD3 color;
  630. {
  631.    double xt, yt;
  632.    int color_index;
  633.  
  634.    if (gMultiTaskCount++ > MAX_TASK_WAIT)
  635.    {
  636.           gMultiTaskCount = 0;
  637.        MacMultiTask();
  638.    }
  639.  
  640.    /* Scale from image size to actual screen pixel size */
  641.    yt = maxy/2 - Y_Display_Scale * y0;
  642.    xt = maxx/2 + X_Display_Scale * x0;
  643.  
  644.    /* Clip the line to the viewport */
  645.    if (xt < 0.0)
  646.       x0 = 0;
  647.    else if (xt > maxx) {
  648.       x0 = maxx - 1;
  649.       }
  650.    else x0 = (int)xt;
  651.    if (yt < 0.0)
  652.       y0 = 0;
  653.    else if (yt > maxy) {
  654.       y0 = maxy;
  655.       }
  656.    else
  657.       y0 = (int)yt;
  658.  
  659.    yt = maxy/2 - Y_Display_Scale * y1;
  660.    xt = maxx/2 + X_Display_Scale * x1;
  661.    if (xt < 0.0)
  662.       x1 = 0;
  663.    else if (xt > maxx) {
  664.       x1 = maxx - 1;
  665.       }
  666.    else x1 = (int)xt;
  667.    if (yt < 0.0)
  668.       y1 = 0;
  669.    else if (yt > maxy) {
  670.       y1 = maxy;
  671.       }
  672.    else
  673.       y1 = (int)yt;
  674.  
  675. #if defined(USE_CUSTOM_PALETTE)
  676.    color_index = determine_color_index(color);
  677.    PmForeColor(color_index);
  678. #else
  679.    {
  680.    RGBColor    rgbc;
  681.  
  682.    Coord3ToRGBColor(color, &rgbc);
  683.    RGBForeColor(&rgbc);
  684.    }
  685. #endif
  686.    MoveTo(x0, y0);
  687.    LineTo(x1, y1);
  688. }
  689.  
  690.  
  691. /*------------------------------------------------------------*/
  692. /* general dialog constants */
  693. #define    Ditem_ET_SizePrompt        4
  694. #define    Ditem_BT_GetInFile        5
  695. #define    Ditem_ST_InFileName        6
  696. #define    Ditem_RB_RTO_BuiltIn    7
  697. #define    Ditem_RB_RTO_TriMesh    8
  698. #define    Ditem_PU_OutFormat        9
  699. #define    Ditem_ST_SizeText1        10
  700. #define    Ditem_ST_SizeText2        11
  701. #define    Ditem_ST_RTO_Title        12
  702. #define    Ditem_MAX                Ditem_ST_RTO_Title
  703.  
  704. // STR# resource IDs for this dialog
  705. #define    StrID_APP_NAME            2000
  706. #define    StrID_SIZE_PROMPT        2001
  707. #define    StrID_INFILE_PROMPT        2002
  708. #define    StrID_PATCH_PROMPT        2003
  709.  
  710. // popup menu ID
  711. #define    MenuID_OutFormat        1000
  712.  
  713. /*------------------------------------------------------------*/
  714. /* Put up dialog of options, and return TRUE if user clicks ok, else FALSE if cancel */
  715. static Boolean GetUserOptions(int spdType)
  716. {
  717.     short            itemHit;
  718.     short            k, dummy;
  719.     DialogPtr        myDialog;
  720.     Rect            displayRect;
  721.     ControlHandle    theDItems[Ditem_MAX+1];
  722.     char            aString[64];
  723.     Str15            thePatchPrompt;
  724.     Str31            appVers;
  725.     Str63            theInFilePrompt;
  726.     Str63            theAppName;
  727.     Str255            theSizePrompt;
  728.  
  729.     // load the dialog
  730.     myDialog = SetupNewDialog(DlogID_GETOPTS, true);
  731.     if (!myDialog)
  732.     {
  733.         SysBeep(4);
  734.         ExitToShell();
  735.     }
  736.  
  737.     // preload all the dialog items we care about
  738.     for (k = 1; k<=Ditem_MAX; k++)
  739.         GetDItem(myDialog, k, &dummy, (Handle *) &theDItems[k], &displayRect);
  740.  
  741.     // Get app-specific strings from resources
  742.     GetIndString(theAppName,        StrID_APP_NAME,        spdType);
  743.     GetIndString(theSizePrompt,        StrID_SIZE_PROMPT,    spdType);
  744.     GetIndString(theInFilePrompt,    StrID_INFILE_PROMPT,spdType);
  745.     GetIndString(thePatchPrompt,    StrID_PATCH_PROMPT, spdType);
  746.  
  747.     // SPD Version
  748. //    strcpy(aString, lib_get_version_str());
  749. //    c2pstr(aString);
  750.     // get Mac version from resource instead
  751.     GetAppVersionPString(1, appVers);
  752.  
  753.     // fill in app-specific strings in dialog
  754.     ParamText(theAppName, theSizePrompt, theInFilePrompt, appVers);
  755.  
  756.     // see which dialog items to remove.  Some of these items are specific
  757.     // to certain apps only.  If the Size prompt resource string is empty,
  758.     // don't display the size prompt stuff.
  759.     gHasSizePrompt        = (theSizePrompt[0] != '\0');
  760.  
  761.     // If infile prompt is empty, don't display it.
  762.     gHasInFilePrompt    = (theInFilePrompt[0] != '\0');
  763.  
  764.     // If infile prompt is empty, don't display it.
  765.     gHasPatchPrompt    = (thePatchPrompt[0] != '\0');
  766.  
  767.     // Hide any items that we don't want now
  768.     if (!gHasSizePrompt)
  769.     {
  770.         MoveDItem(myDialog, Ditem_ET_SizePrompt, -1000, -1000);
  771.         MoveDItem(myDialog, Ditem_ST_SizeText1,  -1000, -1000);
  772.         MoveDItem(myDialog, Ditem_ST_SizeText2,  -1000, -1000);
  773.     }
  774.     if (!gHasInFilePrompt)
  775.     {
  776.         MoveControl(theDItems[Ditem_BT_GetInFile], -1000, -1000);
  777.         MoveDItem(myDialog, Ditem_ST_InFileName,   -1000, -1000);
  778.     }
  779.     if (!gHasPatchPrompt)
  780.     {
  781.         MoveDItem(myDialog, Ditem_ST_RTO_Title,      -1000, -1000);
  782.         MoveControl(theDItems[Ditem_RB_RTO_BuiltIn], -1000, -1000);
  783.         MoveControl(theDItems[Ditem_RB_RTO_TriMesh], -1000, -1000);
  784.     }
  785.  
  786.     // fill initial size value into dialog
  787.     sprintf(aString, "%d", gMacParmSize);
  788.     c2pstr(aString);
  789.     SetIText((Handle) theDItems[Ditem_ET_SizePrompt], (StringPtr)aString);
  790.  
  791.     // Preset the popup to POV-Ray 2 for now
  792.     SetCtlValue(theDItems[Ditem_PU_OutFormat], OUTPUT_POVRAY_20+1);
  793.  
  794.     // select something..
  795.     SelIText(myDialog, Ditem_ET_SizePrompt, 0, -1);
  796.  
  797.     // finally show the user our dialog
  798.     MoveWindowToMaxDevice(myDialog);
  799.     ShowWindow(myDialog);
  800.  
  801.     // prompt until user clicks ok or cancel
  802.     do
  803.     {
  804.         // Set the radio buttons
  805.         SetCtlValue(theDItems[Ditem_RB_RTO_BuiltIn], gMacDoBuiltIn);
  806.         SetCtlValue(theDItems[Ditem_RB_RTO_TriMesh], !gMacDoBuiltIn);
  807.  
  808.         // get user input
  809.         ModalDialog(NULL, &itemHit);
  810.  
  811.         // process some user interface elements
  812.         switch (itemHit)
  813.         {
  814.             case Ditem_RB_RTO_BuiltIn:
  815.                 gMacDoBuiltIn = true;
  816.                 break;
  817.  
  818.             case Ditem_RB_RTO_TriMesh:
  819.                 gMacDoBuiltIn = false;
  820.                 break;
  821.  
  822.             case Ditem_BT_GetInFile:
  823.                 GetInputFile(gInFileName);
  824.                 strcpy(aString, gInFileName);
  825.                 c2pstr(aString);
  826.                 SetIText((Handle) theDItems[itemHit], (StringPtr)aString);
  827.                 break;
  828.  
  829.             case Ditem_PU_OutFormat:
  830.                 break;
  831.         }
  832.     } while ((itemHit != ok) && (itemHit != cancel));
  833.  
  834.     if (itemHit == ok)
  835.     {
  836.  
  837.         // Size
  838.         if (gHasSizePrompt)
  839.         {
  840.             GetIText((Handle) theDItems[Ditem_ET_SizePrompt], (StringPtr)aString);
  841.             p2cstr((StringPtr)aString);
  842.             gMacParmSize = atoi(aString);
  843.             if ((gMacParmSize < 1) || (gMacParmSize > 9))
  844.                 gMacParmSize = 2;
  845.         }
  846.  
  847.         // output format from popup
  848.         gMacRayTracerKind = GetCtlValue(theDItems[Ditem_PU_OutFormat]) - 1;
  849.     }
  850.  
  851.     DisposeDialog(myDialog);
  852.  
  853.     // return TRUE if they hit OK
  854.     return (itemHit == ok);
  855.  
  856. } /* GetUserOptions */
  857.  
  858.  
  859. /*------------------------------------------------------------*/
  860. static void AddArgvOpt(int *argcp, char ***argvp, char * optionStr)
  861. {
  862. #pragma unused (argvp)
  863.     strcpy(argvCurrent, optionStr);
  864.     macArgv[*argcp] = argvCurrent;
  865.     argvCurrent += strlen(argvCurrent)+1; /* skip over string and null */
  866.     (*argcp)++;
  867. }
  868.  
  869.  
  870. /*------------------------------------------------------------*/
  871. void RedrawMyDialog(DialogPtr pDialogPtr)
  872. {
  873.     if (pDialogPtr)
  874.     {
  875.         SelectWindow(pDialogPtr);
  876.         DrawDialog(pDialogPtr);
  877.     }
  878. } // RedrawDialog
  879.  
  880.  
  881. /*------------------------------------------------------------*/
  882. void MacInit(int *argcp, char ***argvp, int spdType)
  883. {
  884.     char    strTemp[10];
  885.  
  886.     // give us another 80k of stack space, 'cause we're so recursive
  887.     SetApplLimit(GetApplLimit() - 80000);
  888.     MaxApplZone();
  889.  
  890.     ToolBoxInit();
  891.     if (!GetUserOptions(spdType))
  892.         ExitToShell();
  893.     else
  894.     {
  895.         SetCursor(*GetCursor(watchCursor));
  896.         if (gMacRayTracerKind != OUTPUT_VIDEO)
  897.         {
  898.             /* put up "please wait" dialog */
  899.             gDialogPtr = SetupNewDialog(DlogID_WAIT, false);
  900.             if (gDialogPtr)
  901.             {
  902.                 ShowWindow(gDialogPtr);
  903.                 RedrawMyDialog(gDialogPtr);
  904.             }
  905.             else
  906.             {
  907.                 SysBeep(4);
  908.                 ExitToShell();
  909.             }
  910.         }
  911.  
  912.         *argcp = 0;            /* Set argc to 1 parm initially */
  913.         *argvp = (char **)&macArgv;    /* point argv to our buffer */
  914.         argvCurrent = (char *)&macArgvBuffer;    /* start at beginning of buffer */
  915.  
  916.         /*==== Program name is always first ====*/
  917.         AddArgvOpt(argcp, argvp, "MacSPD");
  918.  
  919.         /*==== Raytracer Format ====*/
  920.         AddArgvOpt(argcp, argvp, "-r");
  921.         sprintf(strTemp, "%d", gMacRayTracerKind);
  922.         AddArgvOpt(argcp, argvp, strTemp);
  923.  
  924.         /*==== Output Format (OUTPUT_CURVES,OUTPUT_PATCHES) ====*/
  925.         if (gHasPatchPrompt)
  926.         {
  927.             if (gMacDoBuiltIn)
  928.                 AddArgvOpt(argcp, argvp, "-c"); /*OUTPUT_CURVES*/
  929.             else
  930.                 AddArgvOpt(argcp, argvp, "-t"); /*OUTPUT_PATCHES*/
  931.         }
  932.  
  933.         /*==== Size ====*/
  934.         if (gHasSizePrompt)
  935.         {
  936.             AddArgvOpt(argcp, argvp, "-s");
  937.             sprintf(strTemp, "%d", gMacParmSize);
  938.             AddArgvOpt(argcp, argvp, strTemp);
  939.         }
  940.  
  941.         /*==== Input File ====*/
  942.         if (gHasInFilePrompt)
  943.         {
  944.             /* Input file name */
  945.             AddArgvOpt(argcp, argvp, "-f");
  946.             AddArgvOpt(argcp, argvp, gInFileName);
  947.         }
  948.     }
  949. } /* MacInit */
  950.  
  951.  
  952. /*------------------------------------------------------------*/
  953. void MacMultiTask(void)
  954. {
  955.     EventRecord    anEvent;
  956.  
  957.    if (gMultiTaskCount++ > MAX_TASK_WAIT)
  958.    {
  959.           gMultiTaskCount = 0;
  960.  
  961.         WaitNextEvent(everyEvent, &anEvent, 1, NULL);
  962.  
  963.         /* grody hack to redraw dialog on suspend/resume */
  964.         if (anEvent.what == kOSEvent)
  965.             if (((anEvent.message >> 24) & 0x0FF) == kSuspendResumeMessage)
  966.             {    /* high byte of message */
  967.                 /* suspend/resume is also an activate/deactivate */
  968.                 RedrawMyDialog(gDialogPtr);
  969.             }
  970.     }
  971.  
  972. } /* MacMultiTask */
  973.  
  974.  
  975. /*------------------------------------------------------------*/
  976. void MacShutDown(void)
  977. {
  978.     /* remove the Please Wait dialog */
  979.     if (gDialogPtr != NULL)
  980.         {
  981.         DisposeDialog(gDialogPtr);
  982.         gDialogPtr = NULL;
  983.         }
  984. } /* MacShutDown */
  985.